package com.financial.business.yspay.service.impl;

import com.financial.business.yspay.connector.YsBusinessFeign;
import com.financial.business.yspay.connector.YsQueryFeign;
import com.financial.business.yspay.constants.FinancialWithdrawalYsEnumConstants;
import com.financial.business.yspay.dao.FinancialWithdrawalYsDao;
import com.financial.business.yspay.domain.FinancialWithdrawalYsDO;
import com.financial.business.yspay.dto.YsWithdrawalDTO;
import com.financial.business.yspay.dto.balance.YsBalanceAccountDetailDTO;
import com.financial.business.yspay.dto.balance.YsBalanceReturnDTO;
import com.financial.business.yspay.service.FinancialWithdrawalYsService;
import com.financial.business.yspay.utils.DateUtils;
import com.financial.business.yspay.utils.JsonUtils;
import com.financial.business.yspay.utils.ValidateUtils;
import com.financial.business.yspay.utils.apiresult.ApiResult;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@Service
public class FinancialWithdrawalYsServiceImpl implements FinancialWithdrawalYsService {
    public static final Logger logger = LoggerFactory.getLogger(FinancialWithdrawalYsServiceImpl.class);

    @Autowired
    private FinancialWithdrawalYsDao financialWithdrawalYsDao;

    @Autowired
    private YsQueryFeign ysQueryFeign;

    @Autowired
    private YsBusinessFeign ysBusinessFeign;

    @Override
    public FinancialWithdrawalYsDO get(Integer id) {
        return financialWithdrawalYsDao.get(id);
    }

    @Override
    public List<FinancialWithdrawalYsDO> list(Map<String, Object> map) {
        return financialWithdrawalYsDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {
        return financialWithdrawalYsDao.count(map);
    }

    @Override
    public int save(FinancialWithdrawalYsDO financialWithdrawalYs) {
        return financialWithdrawalYsDao.save(financialWithdrawalYs);
    }

    @Override
    public int update(FinancialWithdrawalYsDO financialWithdrawalYs) {
        return financialWithdrawalYsDao.update(financialWithdrawalYs);
    }

    /**
     * 银盛一清提现
     *
     * @param requestParam
     * @return
     */
    @Override
    public ApiResult ysWithdrawal(String requestParam) {
        logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()------监听到平台内部提现完成json为：" + requestParam);
        YsWithdrawalDTO ysWithdrawalDTO = JsonUtils.convertBean(requestParam, YsWithdrawalDTO.class);
        Map<String, Object> mapParams = JsonUtils.jsonToMap(requestParam);
        Object tempParams = mapParams.get("total_amount");
        /*分账金额*/
        String totalAmountStr = tempParams == null ? null : tempParams.toString();
        /*三方支付专用交易单号*/
        tempParams = mapParams.get("out_trade_no");
        String outTradeNo = tempParams == null ? null : tempParams.toString();
        /*对接平台商户号*/
        tempParams = mapParams.get("store_no");
        String storeNo = tempParams == null ? null : tempParams.toString();
        /*提现手续费*/
        tempParams = mapParams.get("withdrawal_fee");
        String withdrawaFeeStr = tempParams == null ? null : tempParams.toString();
        /*回执地址*/
        tempParams = mapParams.get("notify_url");
        String notifyUrl = tempParams == null ? null : tempParams.toString();
        /*提现类型*/
        tempParams = mapParams.get("withdrawal_type");
        String withdrawalType = tempParams == null ? null : tempParams.toString();
        /*提现订单说明*/
        tempParams = mapParams.get("subject");
        String subject = tempParams == null ? null : tempParams.toString();
        /*在银盛开设的平台账户*/
        tempParams = mapParams.get("ys_user_code");
        String ysUserCode = tempParams == null ? null : tempParams.toString();
        /*银行名称*/
        tempParams = mapParams.get("bank_name");
        String bankName = tempParams == null ? null : tempParams.toString();
        /*银行帐号*/
        tempParams = mapParams.get("bank_account_no");
        String bankAccountNo = tempParams == null ? null : tempParams.toString();
        /*对接平台提现单号*/
        tempParams = mapParams.get("withdrawal_no");
        String withdrawalNo = tempParams == null ? null : tempParams.toString();
        /*对接平台编码*/
        tempParams = mapParams.get("platform_no");
        String platformNo = tempParams == null ? null : tempParams.toString();
        if (StringUtils.isBlank(totalAmountStr) || StringUtils.isBlank(outTradeNo)
                || StringUtils.isBlank(storeNo) || StringUtils.isBlank(withdrawaFeeStr)
                || StringUtils.isBlank(withdrawalType) || StringUtils.isBlank(storeNo)
                || StringUtils.isBlank(subject) || StringUtils.isBlank(notifyUrl)
                || StringUtils.isBlank(ysUserCode) || StringUtils.isBlank(bankName)
                || StringUtils.isBlank(bankAccountNo) || StringUtils.isBlank(withdrawalNo)
                || StringUtils.isBlank(platformNo)) {
            logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()------提现必传字段非空校验结果：" + ValidateUtils.validateProperty(ysWithdrawalDTO));
            return ApiResult.failure(ValidateUtils.validateProperty(ysWithdrawalDTO));
        }
        /*设定金额精度*/
        /*提现总金额*/
        BigDecimal totalAmount = new BigDecimal(totalAmountStr).setScale(2, RoundingMode.HALF_UP);
        /*提现手续费*/
        BigDecimal withdrawaFee = new BigDecimal(withdrawaFeeStr).setScale(2, RoundingMode.HALF_UP);
        /*提现结果初始化*/
        try {
            FinancialWithdrawalYsDO financialWithdrawalYsDO = new FinancialWithdrawalYsDO();
            /*通过订单号查询数据库，保证该订单提现数据唯一性*/
            FinancialWithdrawalYsDO financialWithdrawalYsDOInfo=financialWithdrawalYsDao.getOne(outTradeNo);
            logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----通过当前订单号查询历史提现记录,订单号:{}",outTradeNo);
            int res=0;
            if(financialWithdrawalYsDOInfo!=null){
                logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----通过当前订单号查询历史提现记录存在,执行更新操作");
                Map<String,Object> dataParams=new HashMap<>();
                dataParams.put("gmtModified",new Date());
                dataParams.put("state",FinancialWithdrawalYsEnumConstants.ENUM_STATE_WAIT);
                dataParams.put("returnMessage",FinancialWithdrawalYsEnumConstants.ENUM_RETURN_MESSAGE);
                dataParams.put("outTradeNo",outTradeNo);
                /*该订单历史提现金额*/
                BigDecimal totalAmountData=financialWithdrawalYsDOInfo.getTotalAmount();
                logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----通过当前订单号查询订单历史提现金额,订单号:{},提现金额:{}",outTradeNo,totalAmountData);
                /*该订单历史提现状态*/
                String state=financialWithdrawalYsDOInfo.getState();
                logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----通过当前订单号查询历史提现状态,订单号:{},订单状态:{}",outTradeNo,state);
                if(totalAmountData.compareTo(totalAmount)!=0){
                    logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----通过当前订单号历史提现金额与当前金额不符");
                    return ApiResult.failure("该订单历史提现金额与当前金额不符");
                }
                if(state.equals("1")){
                    logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----通过当前订单号历史提现状态为提现成功");
                    return ApiResult.success("该订单历史提现已成功");
                }else{
                    logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----通过当前订单号历史提现状态为提现不成功或未提现");
                    res = financialWithdrawalYsDao.updateInfo(dataParams);
                }
            }else{
                logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----通过当前订单号查询历史提现记录不存在,执行创建保存操作");
                financialWithdrawalYsDO.setGmtCreate(new Date());
                financialWithdrawalYsDO.setIsDelete(FinancialWithdrawalYsEnumConstants.ENUM_ISDELETE_UNDEL);
                financialWithdrawalYsDO.setOutTradeNo(outTradeNo);
                financialWithdrawalYsDO.setResqContent(requestParam);
                financialWithdrawalYsDO.setReturnMessage(FinancialWithdrawalYsEnumConstants.ENUM_RETURN_MESSAGE);
                financialWithdrawalYsDO.setState(FinancialWithdrawalYsEnumConstants.ENUM_STATE_WAIT);
                financialWithdrawalYsDO.setStoreNo(storeNo);
                financialWithdrawalYsDO.setWithdrawalNo(withdrawalNo);
                financialWithdrawalYsDO.setPlatformNo(platformNo);
                financialWithdrawalYsDO.setWithdrawalFee(withdrawaFee);
                financialWithdrawalYsDO.setTotalAmount(totalAmount);
                res = financialWithdrawalYsDao.save(financialWithdrawalYsDO);
            }
            if (res > 0) {
                /*在调用提现之前先调用银盛余额查询接口来查询该商户在银盛的结算余额*/
                Map<String, Object> balanceMap = new HashMap<String, Object>();
                balanceMap.put(FinancialWithdrawalYsEnumConstants.MERCHANT_USERCODE, ysUserCode);
                String balanceJson = JsonUtils.toJSon(balanceMap);
                logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----调用银盛查询余额之前的json数据：" + balanceJson);
                ApiResult apiBalance = this.ysQueryFeign.balance(balanceJson);
                logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----调用银盛查询余额返回apiresult字符串为：" + apiBalance);
                /*解析返回来的余额json*/
                String balanceResult = (String) apiBalance.getResult();
                if (apiBalance.getCode() == FinancialWithdrawalYsEnumConstants.APIRESULT_SUCCESS && balanceResult != null) {
                    YsBalanceReturnDTO ysBalanceReturnDTO = JsonUtils.convertBean(balanceResult, YsBalanceReturnDTO.class);
                    List<YsBalanceAccountDetailDTO> balanceAccountDetailList = ysBalanceReturnDTO.getAccount_detail();
                    String accountAmountStr = balanceAccountDetailList.get(0).getAccount_amount();
                    BigDecimal accountAmount = new BigDecimal(accountAmountStr);
                    logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----银盛返回一般商户余额为：" + accountAmount);
                    /*银盛余额大于提现金额加上手续费方可提现*/
                    if (accountAmount.compareTo(totalAmount.add(withdrawaFee)) >= 0) {
                        /*组装银盛提现业务参数格式*/
                        Map<String, Object> ysWithdrawalMap = new ConcurrentHashMap<>();
                        ysWithdrawalMap.put("bank_account_no", bankAccountNo);
                        ysWithdrawalMap.put("shopdate", DateUtils.formatDate("yyyyMMdd"));
                        ysWithdrawalMap.put("subject", subject);
                        ysWithdrawalMap.put("total_amount", totalAmount);
                        ysWithdrawalMap.put("currency", FinancialWithdrawalYsEnumConstants.ENUM_CURRENCY_CNY);
                        ysWithdrawalMap.put("out_trade_no", outTradeNo);
                        ysWithdrawalMap.put("merchant_usercode", ysUserCode);
                        String ysWithdrawalJson = JsonUtils.toJSon(ysWithdrawalMap);
                        /*调用银盛提现----方可提现*/
                        ApiResult withdrawalResult = ysBusinessFeign.withdrawal(ysWithdrawalJson);
                        logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----调用银盛返回提现结果:" + withdrawalResult);
                        String apiResultMsg = (String) withdrawalResult.getResult();
                        Map<String, Object> condMap = new HashMap<>();
                        condMap.put("outTradeNo", outTradeNo);
                        condMap.put("returnMessage", apiResultMsg);
                        condMap.put("gmtModified", new Date());
                        if (withdrawalResult.getCode() == FinancialWithdrawalYsEnumConstants.APIRESULT_SUCCESS && withdrawalResult != null) {
                            /*返回成功信息进行更改数据库处理*/
                            condMap.put("state", FinancialWithdrawalYsEnumConstants.ENUM_STATE_SUC);
                            int updateState = financialWithdrawalYsDao.updateInfo(condMap);
                            if (updateState > 0) {
                                /*返回成功给对接方*/
                                return ApiResult.success(withdrawalResult);
                            }
                            /*返回失败给对接方*/
                            return ApiResult.failure(withdrawalResult);
                        } else {
                            /*调用银盛提现返回异常*/
                            condMap.put("state", FinancialWithdrawalYsEnumConstants.ENUM_STATE_FAIL);
                            financialWithdrawalYsDao.updateInfo(condMap);
                            logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----调用银盛提现返回异常，返回信息为：" + withdrawalResult);
                            return ApiResult.failure(withdrawalResult);
                        }

                    } else {
                        /*提现金额和银盛平台余额有问题，请检查*/
                        logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----提现金额和银盛平台余额有问题，提现金额为：" + totalAmountStr + "---银盛平台余额为：" + accountAmountStr + "---手续费为:" + withdrawaFeeStr);
                        return ApiResult.failure(accountAmount);
                    }
                } else {
                    /*获取银盛银盛余额查询失败*/
                    logger.info("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----获取银盛银盛余额查询失败，返回信息为：" + apiBalance);
                    return ApiResult.failure(apiBalance);
                }
            } else {
                /*参数校验失败，落库失败*/
                return ApiResult.failure(res);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("FinancialWithdrawalYsServiceImpl.ysWithdrawal()-----提现异常：" + e.getMessage());
        }
        return ApiResult.failure(requestParam);
    }

    /**
     * 查询银盛提现记录
     *
     * @param condMap
     * @return
     */
    @Override
    public String query(Map<String, Object> condMap) {

        return financialWithdrawalYsDao.query(condMap);
    }

}
